

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.ico">
  <link rel="icon" href="/img/favicon.ico">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="叶尘的技术升级小木屋">
  <meta name="author" content="叶尘">
  <meta name="keywords" content="">
  
  <title>19、IO 流 - 叶尘的技术升级小木屋</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10.7.2/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
  



<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->

  
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/shubiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/gundongtiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/daziyanse.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/toubudaziji.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"www.yechen-blog.cn","root":"/","version":"1.8.11","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>YECHEN</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-qrcode"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/playlist/">
                <i class="iconfont icon-music"></i>
                音乐
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" target="_self" role="button"
                 data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                链接
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/">
                    
                    主题博客
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/guide/">
                    
                    配置指南
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/icon/">
                    
                    图标用法
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://www.bilibili.com">
                    
                    哔哩哔哩
                  </a>
                
              </div>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/banner.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="19、IO 流">
              
            </span>

            
              <div class="mt-3">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-author" aria-hidden="true"></i>
      叶尘
    </span>
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-09-13 22:22" pubdate>
        星期一, 九月 13日 2021, 10:22 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      6.5k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      86
       分钟
    </span>
  

  
  
    
      <!-- LeanCloud 统计文章PV -->
      <span id="leancloud-page-views-container" class="post-meta" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="leancloud-page-views"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">19、IO 流</h1>
            
            <div class="markdown-body">
              <h3 id="19-1-IO流概述"><a href="#19-1-IO流概述" class="headerlink" title="19.1 IO流概述"></a>19.1 IO流概述</h3><h4 id="19-1-1-什么是-IO-流"><a href="#19-1-1-什么是-IO-流" class="headerlink" title="19.1.1 什么是 IO 流"></a>19.1.1 什么是 IO 流</h4><p>I : Input</p>
<p>O : Output</p>
<p>==<strong>通过IO可以完成硬盘文件的读和写。</strong>==</p>
<p><img src="https://img-blog.csdnimg.cn/20210222222354471.png" srcset="/img/loading.gif" lazyload alt="001-什么是IO"></p>
<h4 id="19-1-2-IO流的分类"><a href="#19-1-2-IO流的分类" class="headerlink" title="19.1.2 IO流的分类"></a>19.1.2 IO流的分类</h4><p><strong>一种方式是按照流的方向进行分类：</strong></p>
<p>以内存作为参照物</p>
<ul>
<li>往内存中去，叫做==输入(Input)==。或者叫做==读(Read)==</li>
<li>从内存中出来，叫做==输出(Output)==。或者叫做==写(Write)==</li>
</ul>
<p><strong>另一种方式是按照读取数据方式不同进行分类：</strong></p>
<ul>
<li><p>有的流是按照  <strong>==字节==</strong>  的方式读取数据，<strong>一次读取1个字节byte</strong>，等同于一次读取8个二进制位。</p>
<p><strong>这种流是万能的，什么类型的文件都可以读取</strong>。包括：文本文件，图片，声音文件，视频文件等….</p>
<p>假设文件file1.txt，采用字节流的话是这样读的：</p>
<p>​    <strong>a中国bc张三fe</strong></p>
<p>​    第一次读：一个字节，正好读到’a’</p>
<p>​    第二次读：一个字节，正好读到’中’字符的一半。（’a’字符在windows系统中占用1个字节。）</p>
<p>​    第三次读：一个字节，正好读到’中’字符的另外一半。（’中’字符在windows系统中占用2个字节。）</p>
</li>
<li><p>有的流是按照  ==<strong>字符</strong>==  的方式读取数据的，<strong>一次读取一个字符</strong>，这种流是为了<strong>方便读取普通文本文件</strong>而存在的，这种流不能读取：图片、声音、视频等文件。只能读取纯文本文件（不能读取 word 文件）</p>
<p>假设文件file1.txt，采用字符流的话是这样读的：</p>
<p>​    <strong>a中国bc张三fe</strong></p>
<p>​    第一次读：’a’字符（’a’字符在windows系统中占用1个字节。）</p>
<p>​    第二次读：’中’字符（’中’字符在windows系统中占用2个字节。）</p>
</li>
</ul>
<h4 id="19-1-3-java-IO流四大家族"><a href="#19-1-3-java-IO流四大家族" class="headerlink" title="19.1.3 java IO流四大家族"></a>19.1.3 java IO流四大家族</h4><p><strong>四大家族的首领（都是抽象类）：</strong></p>
<ul>
<li>java.io.InputStream（字节输入流）</li>
<li>java.io.OutputStream（字节输出流）</li>
<li>java.io.Reader（字符输入流）</li>
<li>java.io.Writer（字符输出流）</li>
</ul>
<p><strong>==所有的流==都实现了:</strong></p>
<ul>
<li><p><code>java.io.Closeable</code> 接口：都是可关闭的，都有<code>close() </code>方法。</p>
<p>流毕竟是一个管道，这个是内存和硬盘之间的通道，<strong>用完之后一定要关闭，不然会耗费(占用)很多资源</strong>。养成好习惯，用完流一定要关闭。</p>
</li>
</ul>
<p><strong>所有的==输出流==都实现了：</strong></p>
<ul>
<li><p><code>java.io.Flushable</code> 接口，都是可刷新的，都有<code>flush()</code> 方法。</p>
<p>养成一个好习惯，输出流在最终输出之后，一定要记得 flush() 刷新一下。这个<strong>刷新表示将通道/管道当中剩余未输出的数据强行输出完</strong>（清空管道！）刷新的作用就是清空管道。</p>
<p><strong>注意：如果没有flush()可能会导致丢失数据</strong>。</p>
</li>
</ul>
<p><strong>==注意：在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流。==</strong></p>
<h4 id="19-1-4-java-io包下需要掌握的流有16个"><a href="#19-1-4-java-io包下需要掌握的流有16个" class="headerlink" title="19.1.4 java.io包下需要掌握的流有16个"></a>19.1.4 java.io包下需要掌握的流有16个</h4><p><strong>文件专属：</strong></p>
<ul>
<li><code>java.io.FileInputStream</code>（掌握）</li>
<li><code>java.io.FileOutputStream</code>（掌握）</li>
<li><code>java.io.FileReader</code></li>
<li><code>java.io.FileWriter</code></li>
</ul>
<p><strong>转换流：（将字节流转换成字符流）:</strong></p>
<ul>
<li><code>java.io.InputStreamReader</code></li>
<li><code>java.io.OutputStreamWriter</code></li>
</ul>
<p><strong>缓冲流专属：</strong></p>
<ul>
<li><p><code>java.io.BufferedReader</code></p>
</li>
<li><p><code>java.io.BufferedWriter</code></p>
</li>
<li><p><code>java.io.BufferedInputStream</code></p>
</li>
<li><p><code>java.io.BufferedOutputStream</code></p>
</li>
</ul>
<p><strong>数据流专属：</strong> </p>
<ul>
<li><p><code>java.io.DataInputStream</code></p>
</li>
<li><p><code>java.io.DataOutputStream</code></p>
</li>
</ul>
<p><strong>标准输出流：</strong></p>
<ul>
<li><p><code>java.io.PrintWriter</code></p>
</li>
<li><p><code>java.io.PrintStream</code>（掌握）</p>
</li>
</ul>
<p><strong>对象专属流：</strong></p>
<ul>
<li><p><code>java.io.ObjectInputStream（掌握）</code></p>
</li>
<li><p><code>java.io.ObjectOutputStream（掌握）</code></p>
</li>
</ul>
<h3 id="19-2-FileInputStream"><a href="#19-2-FileInputStream" class="headerlink" title="19.2 FileInputStream"></a>19.2 FileInputStream</h3><h4 id="19-2-1-概述"><a href="#19-2-1-概述" class="headerlink" title="19.2.1 概述"></a>19.2.1 概述</h4><ul>
<li><strong>文件字节输入流，万能的，任何类型的文件都可以采用这个流来读。</strong></li>
<li>字节的方式，完成输入的操作，完成读的操作（==硬盘—&gt; 内存==）</li>
</ul>
<h4 id="19-2-2-简单使用"><a href="#19-2-2-简单使用" class="headerlink" title="19.2.2 简单使用"></a>19.2.2 简单使用</h4><ul>
<li>构造方法中可以放文件的路径</li>
<li>当文件不在 IDEA 项目文件下时，要使用<strong>绝对路径</strong></li>
<li>当文件在 IDEA 项目下是，可以使用相对路径，<strong>默认路径是当前项目的根目录</strong></li>
<li><strong>流使用完一定要在 finally 语句块中关闭</strong></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">int</span>	<span class="hljs-title">read</span><span class="hljs-params">()</span><span class="hljs-comment">// 从输入流中读取一个字节的数据，返回值是读取到的字符的 ASCII 码，当数据被读完的时候会返回 -1</span></span><br><span class="hljs-function"><span class="hljs-keyword">int</span>	<span class="hljs-title">read</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] b)</span><span class="hljs-comment">// 从输入流中读取最多b.length字节的数据到字节数组中，返回值是此次往 byte 数组中存放的字节个数，当数据读完的时候会返回 -1</span></span><br><span class="hljs-function"><span class="hljs-keyword">int</span>	<span class="hljs-title">read</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] b, <span class="hljs-keyword">int</span> off, <span class="hljs-keyword">int</span> len)</span><span class="hljs-comment">// 从输入流中读取多达len字节的数据到一个字节数组中。</span></span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs java">FileInputStream fileInputStream = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 构造方法中可以放文件的路径</span><br>    <span class="hljs-comment">// 当文件不在 IDEA 项目文件下时，要使用绝对路径</span><br>    <span class="hljs-comment">// 当文件在 IDEA 项目下是，可以使用相对路径，默认路径是当前项目的根目录</span><br>    fileInputStream = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;src//cn//yechen//myfile.txt&quot;</span>);<br><br>    <span class="hljs-comment">// 读文件，一次读取一个字节byte，这样内存和硬盘交互太频繁，基本上 时间/资源 都耗费在交互上面了</span><br>    <span class="hljs-keyword">int</span> read = <span class="hljs-number">0</span>;<br>    <span class="hljs-keyword">while</span> ((read = fileInputStream.read()) != -<span class="hljs-number">1</span>) &#123;<br>        System.out.println(read);<span class="hljs-comment">// 这里输出的都是字符的 ASCII 码</span><br>    &#125;<br><br>    <span class="hljs-comment">// 一次读 byte.length 个字节</span><br>    <span class="hljs-keyword">byte</span>[] bytes = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">10</span>];<br>    <span class="hljs-keyword">int</span> readCount = <span class="hljs-number">0</span>;<br>    StringBuffer buffer = <span class="hljs-keyword">new</span> StringBuffer();<br>    <span class="hljs-keyword">while</span> ((readCount = fileInputStream.read(bytes)) != -<span class="hljs-number">1</span>) &#123;<br>        <span class="hljs-comment">// 使用 String 类的构造方法，将 byte 数组转变为字符串（起始下标为 0， 长度为 reedCount）</span><br>        String string = <span class="hljs-keyword">new</span> String(bytes, <span class="hljs-number">0</span>, readCount);<br>        buffer.append(string);<br>    &#125;<br>    System.out.println(buffer);<br><br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-comment">// 流使用完一定要记得关闭</span><br>    <span class="hljs-comment">// 关闭流的前提是流不是空的，避免空指针异常</span><br>    <span class="hljs-keyword">if</span> (fileInputStream != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            fileInputStream.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="19-2-3-其他方法"><a href="#19-2-3-其他方法" class="headerlink" title="19.2.3 其他方法"></a>19.2.3 其他方法</h4><p><code>int available()</code> ：返回流当中剩余的没有读到的字节数量</p>
<p><strong>可以在读取小文件的时候将此方法的返回值作为 byte 数组的长度，一次直接读完方放到 byte 数组中。</strong></p>
<p>但是不适用于读取大文件，因为数组的内存空间是连续的，找不到一块很大的连续内存空间来存放 byte 数组。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java">FileInputStream fileInputStream = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;src//cn//yechen//myfile.txt&quot;</span>);<br><br><span class="hljs-keyword">int</span> available = fileInputStream.available();<br>System.out.println(<span class="hljs-string">&quot;还剩多少字节可以读：&quot;</span> + available);<span class="hljs-comment">// 输出：还剩多少字节可以读：119</span><br><br><span class="hljs-keyword">int</span> read = fileInputStream.read();<span class="hljs-comment">// 读了一个字节</span><br>System.out.println(<span class="hljs-string">&quot;还剩多少字节可以读：&quot;</span> + fileInputStream.available());<span class="hljs-comment">// 输出：还剩多少字节可以读：118</span><br><br>myfile.txt -&gt;<br>    <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Hello</span> </span>&#123;<br>        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>            System.out.println(<span class="hljs-string">&quot;HelloWorld&quot;</span>);<br>        &#125;<br>    &#125;<br></code></pre></td></tr></table></figure>

<p><code>long skip(long n)</code>： 跳过 n 个字节不读</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java">FileInputStream fileInputStream = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;src//cn//yechen//myfile02.txt&quot;</span>);<br>System.out.println(<span class="hljs-string">&quot;第一次读到：&quot;</span> + fileInputStream.read());<span class="hljs-comment">// 输出：第一次读到：97（a）</span><br><br><span class="hljs-comment">// 跳过三个字节（bcd）</span><br>fileInputStream.skip(<span class="hljs-number">3</span>);<br><br>System.out.println(<span class="hljs-string">&quot;第二次读到：&quot;</span> + fileInputStream.read());<span class="hljs-comment">// 输出：第二次读到：101（e）</span><br><br>myfile02.txt -&gt; <br>    abcdefg<br></code></pre></td></tr></table></figure>





<h3 id="19-3-FileOutputStream"><a href="#19-3-FileOutputStream" class="headerlink" title="19.3 FileOutputStream"></a>19.3 FileOutputStream</h3><p>文件字节输出流，负责写。</p>
<p><strong>从内存到硬盘。</strong></p>
<p><strong>输出流在写完之后一定要记得刷新。</strong></p>
<p><strong>简单使用：</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs java">FileOutputStream fileOutputStream = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 这种方式谨慎使用，这种方式会先将原文件清空，然后重新写入。</span><br>    <span class="hljs-comment">// fileOutputStream = new FileOutputStream(&quot;src//cn//yechen//myfile03.txt&quot;);</span><br>    <span class="hljs-comment">// 以追加的方式在文件末尾写入。不会清空原文件内容。</span><br>    <span class="hljs-comment">// 文件不存在的时候会自动创建</span><br>    fileOutputStream = <span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">&quot;src//cn//yechen//myfile03.txt&quot;</span>, <span class="hljs-keyword">true</span>);<br><br>    <span class="hljs-keyword">byte</span>[] bytes = &#123;<span class="hljs-number">97</span>,<span class="hljs-number">98</span>,<span class="hljs-number">99</span>,<span class="hljs-number">100</span>,<span class="hljs-number">101</span>,<span class="hljs-number">102</span>&#125;;<br>    <span class="hljs-comment">// 将 byte 数组写入文件</span><br>    fileOutputStream.write(bytes);<br><br>    String string = <span class="hljs-string">&quot;我是中国人&quot;</span>;<br>    <span class="hljs-comment">// 将 string 字符串先转变为 byte 数组在写入文件</span><br>    <span class="hljs-keyword">byte</span>[] bytes1 = string.getBytes();<br>    fileOutputStream.write(bytes1);<br><br>    <span class="hljs-comment">// 使用完流记得刷新一下</span><br>    fileOutputStream.flush();<br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-keyword">if</span> (fileOutputStream != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            fileOutputStream.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br><br>myfile03 -&gt;<br>    abcdef我是中国人<br></code></pre></td></tr></table></figure>



<h3 id="19-4-FileReader-FileWriter"><a href="#19-4-FileReader-FileWriter" class="headerlink" title="19.4 FileReader / FileWriter"></a>19.4 FileReader / FileWriter</h3><p><strong>文件字符输入流，只能读取普通文本。</strong></p>
<p>读取文本内容时，比较方便，快捷。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java">FileReader reader = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 创建字符输入流</span><br>    reader = <span class="hljs-keyword">new</span> FileReader(<span class="hljs-string">&quot;src//cn//yechen//myfile.txt&quot;</span>);<br><br>    <span class="hljs-keyword">char</span>[] chars = <span class="hljs-keyword">new</span> <span class="hljs-keyword">char</span>[<span class="hljs-number">1024</span> * <span class="hljs-number">512</span>];<span class="hljs-comment">// 一次读取 1 MB</span><br>    <span class="hljs-keyword">int</span> readCount = <span class="hljs-number">0</span>;<br>    <span class="hljs-comment">// 开始读</span><br>    <span class="hljs-keyword">while</span> ((readCount = reader.read(chars)) != -<span class="hljs-number">1</span>) &#123;<br>        System.out.println(<span class="hljs-keyword">new</span> String(chars, <span class="hljs-number">0</span>, readCount));<br>    &#125;<br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-keyword">if</span> (reader != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            reader.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<p><strong>文件字符输出流。只能输出普通文本。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java">FileWriter fileWriter = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 创建字符输出流对象</span><br>    fileWriter = <span class="hljs-keyword">new</span> FileWriter(<span class="hljs-string">&quot;src//cn//yechen//myfile02.txt&quot;</span>);<br>    <span class="hljs-comment">// 开始写</span><br>    <span class="hljs-keyword">char</span>[] chars = &#123;<span class="hljs-string">&#x27;我&#x27;</span>, <span class="hljs-string">&#x27;是&#x27;</span>, <span class="hljs-string">&#x27;中&#x27;</span>, <span class="hljs-string">&#x27;国&#x27;</span>, <span class="hljs-string">&#x27;人&#x27;</span>, <span class="hljs-string">&#x27;！&#x27;</span>&#125;;<br>    <span class="hljs-comment">// 可以传进char数组</span><br>    fileWriter.write(chars);<br>    <span class="hljs-comment">// 可以传进字符串</span><br>    fileWriter.write(<span class="hljs-string">&quot;我是中国人！&quot;</span>);<br>    <span class="hljs-comment">// 刷新流</span><br>    fileWriter.flush();<br><br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-keyword">if</span> (fileWriter != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            fileWriter.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="19-5-BufferedReader-BufferWriter"><a href="#19-5-BufferedReader-BufferWriter" class="headerlink" title="19.5 BufferedReader / BufferWriter"></a>19.5 BufferedReader / BufferWriter</h3><p><strong>BufferedReader:</strong></p>
<ul>
<li>带有缓冲区的字符输入流。</li>
<li>使用这个流的时候不需要自定义char数组，或者说不需要自定义byte数组。自带缓冲。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs java">FileReader fileReader = <span class="hljs-keyword">null</span>;<br>BufferedReader bufferedReader = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    fileReader = <span class="hljs-keyword">new</span> FileReader(<span class="hljs-string">&quot;src\\io\\copy\\CopyTest01.java&quot;</span>);<br>    <span class="hljs-comment">// 当一个流的构造方法中需要一个流的时候，这个被传进来的流叫做：节点流。</span><br>    <span class="hljs-comment">// 外部负责包装的这个流，叫做：包装流，还有一个名字叫做：处理流。</span><br>    <span class="hljs-comment">// 像当前这个程序来说：FileReader就是一个节点流。BufferedReader就是包装流/处理流。</span><br>    bufferedReader = <span class="hljs-keyword">new</span> BufferedReader(fileReader);<br>    String s;<br>    <span class="hljs-comment">// bufferedReader.readLine()方法读取一个文本行，但不带换行符。</span><br>    <span class="hljs-keyword">while</span> ((s = bufferedReader.readLine()) != <span class="hljs-keyword">null</span>) &#123;<br>        System.out.println(s);<br>    &#125;<br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-comment">// 只需要关闭最外层的包装流就行了</span><br>    <span class="hljs-keyword">if</span> (bufferedReader != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            bufferedReader.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>BufferWriter：</strong></p>
<ul>
<li>带有缓冲的字符输出流</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java">BufferedWriter bufferedWriter = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    bufferedWriter = <span class="hljs-keyword">new</span> BufferedWriter(<span class="hljs-keyword">new</span> FileWriter(<span class="hljs-string">&quot;src//cn//yechen//myfile02.txt&quot;</span>));<br>    <span class="hljs-comment">// 可以写入一个字符串</span><br>    bufferedWriter.write(<span class="hljs-string">&quot;我是中国人&quot;</span>);<span class="hljs-comment">// 写入：“我是中国人”</span><br><br>    <span class="hljs-comment">// 可以写入一个 char 数组的一部分</span><br>    <span class="hljs-keyword">char</span>[] chars = &#123;<span class="hljs-string">&#x27;我&#x27;</span>,<span class="hljs-string">&#x27;是&#x27;</span>,<span class="hljs-string">&#x27;中&#x27;</span>,<span class="hljs-string">&#x27;国&#x27;</span>,<span class="hljs-string">&#x27;人&#x27;</span>&#125;;<br>    bufferedWriter.write(chars, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>);<span class="hljs-comment">// 写入：“中国人”</span><br><br>    <span class="hljs-comment">// 刷新输出流</span><br>    bufferWriter.flush();<br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-keyword">if</span> (bufferedWriter != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            bufferedWriter.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>节点流和包装流：</strong></p>
<p>当一个流的构造方法中需要一个流的时候，这个被传进来的流叫做：节点流。</p>
<p> 外部负责包装的这个流，叫做：包装流，还有一个名字叫做：处理流。</p>
<p><strong>关闭流的时候只需要关闭最外层的包装流即可。</strong></p>
<p>节点流和包装流是相对的。</p>
<h3 id="19-6-InputStreamReader-OutputStreamWriter"><a href="#19-6-InputStreamReader-OutputStreamWriter" class="headerlink" title="19.6 InputStreamReader / OutputStreamWriter"></a>19.6 InputStreamReader / OutputStreamWriter</h3><p><strong>转换流</strong></p>
<p><code>InputStreamReader</code> ： 将字节输入流转换为字符输入流。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">FileInputStream fileInputStream = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;&quot;</span>);<br>InputStreamReader inputStreamReader = <span class="hljs-keyword">new</span> InputStreamReader(fileInputStream);<br></code></pre></td></tr></table></figure>

<p><code>OutputStreamWriter</code> ： 将字节输出流转换为字符输出流。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">FileOutputStream fileOutputStream = <span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">&quot;&quot;</span>);<br>OutputStreamWriter outputStreamWriter = <span class="hljs-keyword">new</span> OutputStreamWriter(fileOutputStream);<br></code></pre></td></tr></table></figure>



<h3 id="19-7-DataOutputStream-DataInputStream"><a href="#19-7-DataOutputStream-DataInputStream" class="headerlink" title="19.7 DataOutputStream / DataInputStream"></a>19.7 DataOutputStream / DataInputStream</h3><p><strong>DataOutputStream：</strong>数据专属的流</p>
<p>这个流可以将数据连同数据的类型一并写入文件。</p>
<p>注意：这个文件不是普通文本文档。（这个文件使用记事本打不开。）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs java">DataOutputStream dataOutputStream = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    dataOutputStream = <span class="hljs-keyword">new</span> DataOutputStream(<span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">&quot;data&quot;</span>));<br>    <span class="hljs-comment">// 写数据</span><br>    <span class="hljs-keyword">byte</span> b = <span class="hljs-number">13</span>;<br>    <span class="hljs-keyword">int</span> i = <span class="hljs-number">1000</span>;<br>    <span class="hljs-keyword">double</span> d = <span class="hljs-number">222</span>;<br>    <span class="hljs-keyword">boolean</span> flag = <span class="hljs-keyword">true</span>;<br>    <span class="hljs-keyword">char</span> c = <span class="hljs-string">&#x27;a&#x27;</span>;<br><br>    <span class="hljs-comment">// 写</span><br>    dataOutputStream.writeByte(b);<br>    dataOutputStream.writeInt(i);<br>    dataOutputStream.writeDouble(d);<br>    dataOutputStream.writeBoolean(flag);<br>    dataOutputStream.writeChar(c);<br><br>    <span class="hljs-comment">// 刷新数据流</span><br>    dataOutputStream.flush();<br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-keyword">if</span> (dataOutputStream != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            dataOutputStream.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>DataInputStream：</strong> 数据字节输入流</p>
<p>DataOutputStream 写的文件，只能使用 DataInputStream 去读。并且读的时候你需要提前知道写入的顺序。</p>
<p>读的顺序需要和写的顺序一致。才可以正常取出数据。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs java">DataInputStream dataInputStream = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    dataInputStream = <span class="hljs-keyword">new</span> DataInputStream(<span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;data&quot;</span>));<br>    <span class="hljs-comment">// 开始读</span><br>    <span class="hljs-keyword">byte</span> b = dataInputStream.readByte();<br>    <span class="hljs-keyword">int</span> i = dataInputStream.readInt();<br>    <span class="hljs-keyword">double</span> v = dataInputStream.readDouble();<br>    <span class="hljs-keyword">boolean</span> b1 = dataInputStream.readBoolean();<br>    <span class="hljs-keyword">char</span> c = dataInputStream.readChar();<br><br>    <span class="hljs-comment">// 输出</span><br>    System.out.println(b);<br>    System.out.println(i);<br>    System.out.println(v);<br>    System.out.println(b1);<br>    System.out.println(c);<br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-keyword">if</span> (dataInputStream != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            dataInputStream.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="19-8-PrintStream"><a href="#19-8-PrintStream" class="headerlink" title="19.8 PrintStream"></a>19.8 PrintStream</h3><p>标准的字节输出流。<strong>默认输出到控制台</strong>。</p>
<p>标准输出流<strong>不需要手动close()关闭</strong>。</p>
<p>可以改变标准输出流的输出方向。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 记录标准输出流的默认输出方向（到控制台）</span><br>PrintStream printStream = System.out;<br><span class="hljs-comment">// 改变输出方向</span><br>System.setOut(<span class="hljs-keyword">new</span> PrintStream(<span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">&quot;log&quot;</span>, <span class="hljs-keyword">true</span>)));<span class="hljs-comment">// 为了方便已经抛出异常</span><br><span class="hljs-comment">// 输出到指定路径</span><br>System.out.println(<span class="hljs-string">&quot;zhangsan&quot;</span>);<br>System.out.println(<span class="hljs-string">&quot;lisi&quot;</span>);<br>System.out.println(<span class="hljs-string">&quot;wangwu&quot;</span>);<br><span class="hljs-comment">// 输出到控制台</span><br>printStream.println(<span class="hljs-number">1</span>);<br>printStream.println(<span class="hljs-number">2</span>);<br>printStream.println(<span class="hljs-number">3</span>);<br><br><span class="hljs-comment">// log文件输出</span><br>zhangsan<br>lisi<br>wangwu<br>    <br><span class="hljs-comment">// 控制台输出</span><br><span class="hljs-number">1</span><br><span class="hljs-number">2</span><br><span class="hljs-number">3</span><br></code></pre></td></tr></table></figure>

<p><strong>可以写一个类来打印日志信息，日志信息存放在一个文件中</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyLog</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printLog</span><span class="hljs-params">(String msg)</span> </span>&#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            <span class="hljs-comment">// 改变标准输出流的输出方向</span><br>            System.setOut(<span class="hljs-keyword">new</span> PrintStream(<span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">&quot;log&quot;</span>, <span class="hljs-keyword">true</span>)));<br>            <span class="hljs-comment">// 获取当前时间</span><br>            <span class="hljs-keyword">long</span> nowTimeMillis = System.currentTimeMillis();<br>            Date date = <span class="hljs-keyword">new</span> Date(nowTimeMillis);<br>            SimpleDateFormat simpleDateFormat = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">&quot;yyyy-MM-dd HH:mm:ss SSS&quot;</span>);<br>            String nowTimeStr = simpleDateFormat.format(date);<br>            <span class="hljs-comment">// 输出日志信息</span><br>            System.out.println(nowTimeStr + <span class="hljs-string">&quot;：&quot;</span> + msg);<br>        &#125; <span class="hljs-keyword">catch</span> (FileNotFoundException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="19-9-File"><a href="#19-9-File" class="headerlink" title="19.9 File"></a>19.9 File</h3><p><strong>File类和四大家族没有关系</strong>，所以File类不能完成文件的读和写。</p>
<p>File对象代表：<strong>文件和目录路径名的抽象表示形式。</strong></p>
<ul>
<li>一个目录是一个 File 对象</li>
<li>一个文件也是一个 File 对象</li>
</ul>
<p><strong>一个File对象有可能对应的是目录，也可能是文件。File只是一个路径名的抽象表示形式。</strong></p>
<h4 id="File类中常用的方法："><a href="#File类中常用的方法：" class="headerlink" title="File类中常用的方法："></a>File类中常用的方法：</h4><ol>
<li>创建一个 File 对象</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;D:\\Code\\Java&quot;</span>);<span class="hljs-comment">// 构造方法中跟目录路径或是文件路径，可以存在，也可以不存在</span><br></code></pre></td></tr></table></figure>

<ol start="2">
<li><code>boolean exists()</code> ：判断当前目录或文件<strong>是否存在</strong></li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">boolean</span> isExists = file.exists();<br></code></pre></td></tr></table></figure>

<ol start="3">
<li><code>boolean createNewFile()</code>：<strong>当且仅当具有此名称的文件还不存在时</strong>，才会自动创建一个以该抽象路径名命名的<strong>新空文件</strong>。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 如果当前路径 目录或文件不存在</span><br><span class="hljs-keyword">if</span> (!file.exists()) &#123;<br>    <span class="hljs-comment">// 以文件的形式创建出来</span><br>    file.createNewFile();<br>&#125;<br></code></pre></td></tr></table></figure>

<ol start="4">
<li><code>boolean mkdir()</code>：创建以这个抽象路径名命名的<strong>目录</strong>。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 如果当前路径 目录或文件不存在</span><br><span class="hljs-keyword">if</span> (!file.exists()) &#123;<br>    <span class="hljs-comment">// 以目录的形式创建出来</span><br>    file.mkdir();<br>&#125;<br></code></pre></td></tr></table></figure>

<ol start="5">
<li><code>boolean mkdirs()</code> ： 创建以这个抽象路径名命名的目录，<strong>包括任何必要但不存在的父目录</strong>。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java">File file02 = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;D:\\a\\b\\c&quot;</span>);<br><span class="hljs-keyword">if</span> (!file02.exists()) &#123;<br>    file02.mkdirs();<br>&#125;<br></code></pre></td></tr></table></figure>

<ol start="6">
<li><code>String    getParent()</code> : <strong>返回这个抽象路径名的父路径名字符串</strong>，如果这个路径名没有指定父目录，则返回null。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;D:\\Code\\Java\\JavaLearning&quot;</span>);<br>String parent = file.getParent();<br>System.out.println(parent);<span class="hljs-comment">// D:\Code\Java</span><br></code></pre></td></tr></table></figure>

<ol start="7">
<li><code>File getParentFile()</code> ： <strong>返回这个抽象路径名的父目录的抽象路径名</strong>，如果这个路径名没有指定父目录，则返回null。</li>
<li><code>String getPath()</code> ：将这个抽象的路径名转换为<strong>一个路径名字符串</strong>。</li>
<li><code>String    getAbsolutePath()</code> ：返回这个抽象路径名的<strong>绝对路径名字符串。</strong></li>
<li><code>File getAbsoluteFile()</code> ：返回这个抽象路径名的<strong>绝对形式</strong>。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;src//cn//yechen&quot;</span>);<span class="hljs-comment">// 以 IDEA 根目录为默认路径的 目录</span><br>File parentFile = file.getParentFile();<br>System.out.println(parentFile.getPath());<span class="hljs-comment">// src\cn</span><br>System.out.println(parentFile.getAbsolutePath());<span class="hljs-comment">// C:\Users\30117\Desktop\Demo\src\cn</span><br>File absoluteFile = file.getAbsoluteFile();<br>System.out.println(absoluteFile.getPath());<span class="hljs-comment">// C:\Users\30117\Desktop\Demo\src\cn\yechen</span><br></code></pre></td></tr></table></figure>

<ol start="11">
<li><code>String    getName()</code> ：返回由这个抽象路径名表示的<strong>文件或目录的名称</strong>。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;src//cn//yechen&quot;</span>);<span class="hljs-comment">// 以 IDEA 根目录为默认路径的 目录</span><br>System.out.println(file.getName());<span class="hljs-comment">// Yechen</span><br></code></pre></td></tr></table></figure>

<ol start="12">
<li><p><code>boolean isDirectory()</code> ： 测试此抽象路径名表示的文件<strong>是否为目录</strong>。</p>
</li>
<li><p><code>boolean isFile()</code> ：测试此抽象路径名表示的文件<strong>是否为普通文件</strong>。</p>
</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;src//cn//yechen&quot;</span>);<span class="hljs-comment">// 以 IDEA 根目录为默认路径的 目录</span><br>System.out.println(file.isFile());<span class="hljs-comment">// false</span><br>System.out.println(file.isDirectory());<span class="hljs-comment">// true</span><br></code></pre></td></tr></table></figure>

<ol start="14">
<li><code>long lastModified()</code> ：返回这个抽象路径名所表示的文件<strong>最后一次修改的时间。</strong></li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;D:\\Java基础知识篇.pdf&quot;</span>);<br><span class="hljs-keyword">long</span> lastModified = file.lastModified();<span class="hljs-comment">// 这个毫秒是从1970年到现在的总毫秒数。</span><br>Date date = <span class="hljs-keyword">new</span> Date(lastModified);<br>SimpleDateFormat simpleDateFormat = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">&quot;yyyy-MM-dd HH:mm:ss SSS&quot;</span>);<br>String timeStr = simpleDateFormat.format(date);<br>System.out.println(timeStr);<span class="hljs-comment">// 2020-05-25 09:05:53 000</span><br></code></pre></td></tr></table></figure>

<ol start="15">
<li><code>long length()</code> ：返回由这个抽象路径名表示的<strong>文件的长度（字节）</strong>。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;D:\\Java基础知识篇.pdf&quot;</span>);<br>System.out.println(file.length());<span class="hljs-comment">// 2416894 </span><br></code></pre></td></tr></table></figure>

<ol start="16">
<li><code>File[]    listFiles()</code> ：返回一个<strong>抽象路径名数组</strong>，它表示由这个抽象路径名指定的<strong>目录中的文件</strong>。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;src//cn//yechen&quot;</span>);<br>File[] files = file.listFiles();<br><span class="hljs-comment">// 编历 files</span><br><span class="hljs-keyword">for</span> (File file1 : files) &#123;<br>    System.out.println(file1.getAbsolutePath());<span class="hljs-comment">// 输出目录中文件的绝对路径</span><br>&#125;<br><span class="hljs-comment">/*</span><br><span class="hljs-comment">	输出：</span><br><span class="hljs-comment">		C:\Users\30117\Desktop\Demo\src\cn\yechen\collection</span><br><span class="hljs-comment">        C:\Users\30117\Desktop\Demo\src\cn\yechen\Link</span><br><span class="hljs-comment">        C:\Users\30117\Desktop\Demo\src\cn\yechen\myfile.txt</span><br><span class="hljs-comment">        C:\Users\30117\Desktop\Demo\src\cn\yechen\myfile02.txt</span><br><span class="hljs-comment">        C:\Users\30117\Desktop\Demo\src\cn\yechen\myfile03.txt</span><br><span class="hljs-comment">        C:\Users\30117\Desktop\Demo\src\cn\yechen\MyLog.java</span><br><span class="hljs-comment">        C:\Users\30117\Desktop\Demo\src\cn\yechen\Test.java</span><br><span class="hljs-comment">        C:\Users\30117\Desktop\Demo\src\cn\yechen\Test01</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>



<h3 id="19-10-ObjectInputStream-ObjectOutputStream"><a href="#19-10-ObjectInputStream-ObjectOutputStream" class="headerlink" title="19.10 ObjectInputStream / ObjectOutputStream"></a>19.10 ObjectInputStream / ObjectOutputStream</h3><h4 id="19-10-1-序列化和反序列化"><a href="#19-10-1-序列化和反序列化" class="headerlink" title="19.10.1 序列化和反序列化"></a>19.10.1 序列化和反序列化</h4><ul>
<li>序列化（Serialize）：将 java 对象从内存中存储到文件中，将 java 对象的状态保存下来的过程。</li>
<li>反序列化（DeSerialize）：将硬盘上的数据重新恢复到内存中，恢复成 java 对象。</li>
</ul>
<p><img src="https://img-blog.csdnimg.cn/20210224160626327.png" srcset="/img/loading.gif" lazyload alt="003-对象的序列化和反序列化"></p>
<p>**==参与序列化的类型必须实现 <code>java.io.Serilizable</code> 接口（只是一个标志，不用重写方法==**）</p>
<p>起到标识的作用，标志的作用，java虚拟机看到这个类实现了这个接口，可能会对这个类进行特殊待遇。Serializable这个标志接口是给java虚拟机参考的，<strong>java虚</strong></p>
<p><strong>拟机看到这个接口之后，会为该类自动生成一个序列化版本号。</strong></p>
<p><strong>序列化版本号有什么用呢：</strong></p>
<p>java虚拟机识别一个类的时候先通过类名，<strong>如果类名一致，再通过序列化版本号</strong>。不同的人编写了同一个类，但“这两个类确实不是同一个类”。这个时候序列化版本就起上区分的作用了。</p>
<p>但是对于一个类来说，使用自动序列化版本号之后如果要再次改动代码，重新编译后就会生成不同的序列化版本号，虚拟机就会认为是一个全新的类，就会出现问题。</p>
<p><strong>所以，凡是一个类实现了Serializable接口，建议给该类==提供一个固定不变的序列化版本号==。这样，以后这个类即使代码修改了，但是版本号不变，java虚拟机会认为是同一个类。</strong></p>
<p><strong>IDEA自动生成固定不变的序列化版本号：</strong></p>
<p><img src="https://img-blog.csdnimg.cn/2021022417081334.png" srcset="/img/loading.gif" lazyload alt="image-20210224170751366"></p>
<p><img src="https://img-blog.csdnimg.cn/20210224171046816.png" srcset="/img/loading.gif" lazyload alt="image-20210224171032375"></p>
<p><code>transient</code> <strong>修饰符修饰的属性不参与序列化，该类对象序列化后取出来属性赋类型默认值。</strong></p>
<h4 id="19-10-2-使用"><a href="#19-10-2-使用" class="headerlink" title="19.10.2 使用"></a>19.10.2 使用</h4><p><strong>序列化 / 反序列化单个对象</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 先不管异常，直接抛出</span><br><span class="hljs-comment">// 使用自动序列化版本号</span><br><br><span class="hljs-comment">// 序列化</span><br>ObjectOutputStream objectOutputStream = <span class="hljs-keyword">new</span> ObjectOutputStream(<span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">&quot;student&quot;</span>));<br>objectOutputStream.writeObject(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">&quot;zhangsan&quot;</span>, <span class="hljs-number">20</span>));<br>objectOutputStream.flush();<br>objectOutputStream.close();<br><br><span class="hljs-comment">// 反序列化</span><br>ObjectInputStream objectInputStream = <span class="hljs-keyword">new</span> ObjectInputStream(<span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;student&quot;</span>));<br>Object o = objectInputStream.readObject();<br>System.out.println(o);<span class="hljs-comment">// 输出：Student&#123;name=&#x27;zhangsan&#x27;, age=20&#125;</span><br>objectInputStream.close();<br></code></pre></td></tr></table></figure>

<p><strong>序列化 / 反序列化多个对象（将对象放在集合中）</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 先不管异常，直接抛出</span><br><span class="hljs-comment">// 使用自动序列化版本号</span><br><br><span class="hljs-comment">// 序列化</span><br>ObjectOutputStream objectOutputStream = <span class="hljs-keyword">new</span> ObjectOutputStream(<span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">&quot;student&quot;</span>));<br>List&lt;Student&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();<br>list.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">&quot;zhangsan&quot;</span>, <span class="hljs-number">20</span>));<br>list.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">&quot;lisi&quot;</span>, <span class="hljs-number">21</span>));<br>list.add(<span class="hljs-keyword">new</span> Student(<span class="hljs-string">&quot;wangwu&quot;</span>, <span class="hljs-number">22</span>));<br>objectOutputStream.writeObject(list);<br>objectOutputStream.flush();<br>objectOutputStream.close();<br><br><span class="hljs-comment">// 反序列化</span><br>ObjectInputStream objectInputStream = <span class="hljs-keyword">new</span> ObjectInputStream(<span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;student&quot;</span>));<br>Object o = objectInputStream.readObject();<br><span class="hljs-keyword">if</span> (o <span class="hljs-keyword">instanceof</span> List) &#123;<br>    List&lt;Student&gt; list = (List&lt;Student&gt;) o;<br>    <span class="hljs-keyword">for</span> (Student student : list) &#123;<br>        System.out.println(student);<br>    &#125;<br>&#125;<br>objectInputStream.close();<br><br><span class="hljs-comment">/*</span><br><span class="hljs-comment">	输出：</span><br><span class="hljs-comment">		Student&#123;name=&#x27;zhangsan&#x27;, age=20&#125;</span><br><span class="hljs-comment">        Student&#123;name=&#x27;lisi&#x27;, age=21&#125;</span><br><span class="hljs-comment">        Student&#123;name=&#x27;wangwu&#x27;, age=22&#125;</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>



<h4 id="19-10-3-对序列化版本号的理解"><a href="#19-10-3-对序列化版本号的理解" class="headerlink" title="19.10.3 对序列化版本号的理解"></a>19.10.3 对序列化版本号的理解</h4><p>当一个类实现了 Serializable 接口后，java 虚拟机会自动给这个类加上一个序列化版本号。</p>
<p>当该类对象进行序列化之后，之后如果要修改该类中的代码，然后直接对之前的文件进行反序列化，会出现异常</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java">Exception in thread <span class="hljs-string">&quot;main&quot;</span> java.io.InvalidClassException: （无效的类异常）<br>cn.yechen.test.Student; <br>local <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">incompatible</span>: <span class="hljs-title">stream</span> <span class="hljs-title">classdesc</span> <span class="hljs-title">serialVersionUID</span> </span>= -<span class="hljs-number">8149392996694432981</span>, <br>local <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">serialVersionUID</span> </span>= <span class="hljs-number">2278957827885088367</span><br></code></pre></td></tr></table></figure>

<p><strong>这是由于类修改了之后，该类在重新编译之后，序列化版本号与文件中保存的版本号不同了，因此出现异常，不能反序列化。</strong></p>
<p>因此推荐自己给该类提供一个固定不变的序列化版本号，之后类发生改变，版本号还是一样的。</p>
<p><strong>反序列化得到的信息是与==当前类==中的特征是一样的，不是之前存了多少现在就拿出来多少，例如：如果属性多了，就会给多是属性赋上默认值，如果属性少了，就不会在出现了。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 改动前</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Serializable</span> </span>&#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">long</span> serialVersionUID = -<span class="hljs-number">68497944707546340L</span>;<br>    String name;<br>    <span class="hljs-keyword">int</span> age;<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Student</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>&#123;<br>        <span class="hljs-keyword">this</span>.name = name;<br>        <span class="hljs-keyword">this</span>.age = age;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;Student&#123;&quot;</span> +<br>                <span class="hljs-string">&quot;name=&#x27;&quot;</span> + name + <span class="hljs-string">&#x27;\&#x27;&#x27;</span> +<br>                <span class="hljs-string">&quot;, age=&quot;</span> + age +<br>                <span class="hljs-string">&#x27;&#125;&#x27;</span>;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 序列化 / 反序列化之后输出：</span><br>Student&#123;name=<span class="hljs-string">&#x27;zhangsan&#x27;</span>, age=<span class="hljs-number">20</span>&#125;<br><br><span class="hljs-comment">// 修改后，并且不在序列化</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Serializable</span> </span>&#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">long</span> serialVersionUID = -<span class="hljs-number">68497944707546340L</span>;<br>    String name;<br>    <span class="hljs-keyword">int</span> age;<br>    String address;<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Student</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, String address)</span> </span>&#123;<br>        <span class="hljs-keyword">this</span>.name = name;<br>        <span class="hljs-keyword">this</span>.age = age;<br>        <span class="hljs-keyword">this</span>.address = address;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;Student&#123;&quot;</span> +<br>                <span class="hljs-string">&quot;name=&#x27;&quot;</span> + name + <span class="hljs-string">&#x27;\&#x27;&#x27;</span> +<br>                <span class="hljs-string">&quot;, age=&quot;</span> + age +<br>                <span class="hljs-string">&quot;, address=&#x27;&quot;</span> + address + <span class="hljs-string">&#x27;\&#x27;&#x27;</span> +<br>                <span class="hljs-string">&#x27;&#125;&#x27;</span>;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 反序列化之后，输出</span><br>Student&#123;name=<span class="hljs-string">&#x27;zhangsan&#x27;</span>, age=<span class="hljs-number">20</span>, address=<span class="hljs-string">&#x27;null&#x27;</span>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="19-11-文件复制"><a href="#19-11-文件复制" class="headerlink" title="19.11 文件复制"></a>19.11 <strong>文件复制</strong></h3><h4 id="19-11-1-单个文件的复制粘贴"><a href="#19-11-1-单个文件的复制粘贴" class="headerlink" title="19.11.1 单个文件的复制粘贴"></a>19.11.1 单个文件的复制粘贴</h4><p><strong>使用 FileInputStream 和 FileOutputStream 一边读一边写</strong>（先要将文件读到内存中，再从内从中将文件写到指定路径下）</p>
<p>如果程序没问题，但是复制不成功，出现异常</p>
<p><code>java.io.FileNotFoundException: C:\Java基础知识篇.pdf (拒绝访问。)</code></p>
<p>可以将 IDEA 或命令行工具使用<strong>管理员身份</strong>打开。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 将文件 D:\Java基础知识篇.pdf 拷贝到 C盘下</span><br><span class="hljs-comment">// 创建输入流</span><br>FileInputStream fileInputStream = <span class="hljs-keyword">null</span>;<br><span class="hljs-comment">// 创建输出流</span><br>FileOutputStream fileOutputStream = <span class="hljs-keyword">null</span>;<br><br><span class="hljs-keyword">try</span> &#123;<br>    fileInputStream = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;D:\\Java基础知识篇.pdf&quot;</span>);<br>    fileOutputStream = <span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">&quot;C:\\Java基础知识篇.pdf&quot;</span> );<br><br>    <span class="hljs-comment">// 记录开始时间</span><br>    <span class="hljs-keyword">long</span> begin = System.currentTimeMillis();<br><br>    <span class="hljs-comment">// 核心部分：一边读，一边写</span><br>    <span class="hljs-keyword">byte</span>[] bytes = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">1024</span> * <span class="hljs-number">1024</span>];<span class="hljs-comment">// 一次读 1 MB</span><br>    <span class="hljs-keyword">int</span> readCount = <span class="hljs-number">0</span>;<br>    <span class="hljs-comment">// 一边读</span><br>    <span class="hljs-keyword">while</span> ((readCount = fileInputStream.read(bytes)) != -<span class="hljs-number">1</span>) &#123;<br>        <span class="hljs-comment">// 一边写</span><br>        fileOutputStream.write(bytes, <span class="hljs-number">0</span>, readCount);<br>    &#125;<br><br>    <span class="hljs-comment">// 输出流刷新</span><br>    fileOutputStream.flush();<br><br>    <span class="hljs-comment">// 记录结束时间</span><br>    <span class="hljs-keyword">long</span> end = System.currentTimeMillis();<br>    System.out.println(<span class="hljs-string">&quot;复制总共花费：&quot;</span> + (end - begin) + <span class="hljs-string">&quot; 毫秒&quot;</span>);<br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-comment">// 两个异常要分开解决，如果一起 try 的话，一个流出现异常，另一个流就关闭不了了</span><br>    <span class="hljs-keyword">if</span> (fileInputStream != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            fileInputStream.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>    <span class="hljs-keyword">if</span> (fileOutputStream != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            fileOutputStream.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="19-11-2-目录-文件的复制粘贴"><a href="#19-11-2-目录-文件的复制粘贴" class="headerlink" title="19.11.2 目录 + 文件的复制粘贴"></a>19.11.2 目录 + 文件的复制粘贴</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">import</span> java.io.*;<br><br><span class="hljs-comment">// 拷贝目录 + 文件</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Test</span> </span>&#123;<br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>        <span class="hljs-comment">// 复制源</span><br>        File srcFile = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;D:\\temp&quot;</span>);<br>        <span class="hljs-comment">// 复制目标</span><br>        File destFile = <span class="hljs-keyword">new</span> File(<span class="hljs-string">&quot;D:\\temp02&quot;</span>);<br>        <span class="hljs-comment">// 复制方法</span><br>        copy(srcFile, destFile);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 复制目录方法</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> srcFile 复制源</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destFile 复制目标</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">copy</span><span class="hljs-params">(File srcFile, File destFile)</span> </span>&#123;<br>        <span class="hljs-comment">// 如果源文件是一个文件（不是目录），就进行文件的复制粘贴</span><br>        <span class="hljs-keyword">if</span> (srcFile.isFile()) &#123;<br>            <span class="hljs-comment">// 拼接目标路径（目标路径 + &quot;\\&quot; + 当前文件路径减掉前面 3 个字符（即盘符 D:\））</span><br>            String newFilePath = destFile.getAbsolutePath() + <span class="hljs-string">&quot;\\&quot;</span> + srcFile.getAbsolutePath().substring(<span class="hljs-number">3</span>);<br>            <span class="hljs-comment">// 将目标路径封装成 file 对象，传入文件拷贝方法</span><br>            File file = <span class="hljs-keyword">new</span> File(newFilePath);<br>            copyFile(srcFile, file);<br>            <span class="hljs-comment">// 直接退出当前方法</span><br>            <span class="hljs-keyword">return</span>;<br>        &#125;<br><br>        <span class="hljs-comment">// 程序走到了代表当前文件是一个目录</span><br>        <span class="hljs-comment">// 获取子目录</span><br>        File[] files = srcFile.listFiles();<br>        <span class="hljs-keyword">for</span> (File file : files) &#123;<br>            <span class="hljs-comment">// 如果字目录是一个目录</span><br>            <span class="hljs-keyword">if</span> (file.isDirectory()) &#123;<br>                <span class="hljs-comment">// 拼接目标路径（目标路径 + &quot;\\&quot; + 当前文件路径减掉前面 3 个字符（即盘符 D:\））</span><br>                String newFilePath = destFile.getAbsolutePath() + <span class="hljs-string">&quot;\\&quot;</span> + file.getAbsolutePath().substring(<span class="hljs-number">3</span>);<br>                <span class="hljs-comment">// 将目标路径封装成 file 对象</span><br>                File file1 = <span class="hljs-keyword">new</span> File(newFilePath);<br>                <span class="hljs-comment">// 以目录形式创建</span><br>                <span class="hljs-keyword">if</span> (!file1.exists()) &#123;<br>                    file1.mkdirs();<span class="hljs-comment">// 这里一定啊要注意，是创建多层目录！！！！！！</span><br>                &#125;<br>            &#125;<br>            <span class="hljs-comment">// 进行递归，将当前目录和目标目录传进去</span><br>            copy(file, destFile);<br>        &#125;<br>     &#125;<br>     <br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 文件拷贝方法</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> srcFile 复制源</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> destFile 复制目标</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">copyFile</span><span class="hljs-params">(File srcFile, File destFile)</span> </span>&#123;<br>        FileInputStream fileInputStream = <span class="hljs-keyword">null</span>;<br>        FileOutputStream fileOutputStream = <span class="hljs-keyword">null</span>;<br>        <span class="hljs-keyword">try</span> &#123;<br>            fileInputStream = <span class="hljs-keyword">new</span> FileInputStream(srcFile);<br>            fileOutputStream = <span class="hljs-keyword">new</span> FileOutputStream(destFile);<br>            <span class="hljs-comment">// 一边写一边读</span><br>            <span class="hljs-keyword">byte</span>[] bytes = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">1024</span> * <span class="hljs-number">1024</span>];<span class="hljs-comment">// 一次读 1 MB</span><br>            <span class="hljs-keyword">int</span> readCount = <span class="hljs-number">0</span>;<br>            <span class="hljs-keyword">while</span> ((readCount = fileInputStream.read(bytes)) != -<span class="hljs-number">1</span>) &#123;<br>                fileOutputStream.write(bytes, <span class="hljs-number">0</span>, readCount);<br>            &#125;<br>            <span class="hljs-comment">// 刷新输出流</span><br>            fileOutputStream.flush();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125; <span class="hljs-keyword">finally</span> &#123;<br>            <span class="hljs-keyword">if</span> (fileInputStream != <span class="hljs-keyword">null</span>) &#123;<br>                <span class="hljs-keyword">try</span> &#123;<br>                    fileInputStream.close();<br>                &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>                    e.printStackTrace();<br>                &#125;<br>            &#125;<br>            <span class="hljs-keyword">if</span> (fileOutputStream != <span class="hljs-keyword">null</span>) &#123;<br>                <span class="hljs-keyword">try</span> &#123;<br>                    fileOutputStream.close();<br>                &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>                    e.printStackTrace();<br>                &#125;<br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="19-12-IO-Properties的联合应用"><a href="#19-12-IO-Properties的联合应用" class="headerlink" title="19.12 IO+Properties的联合应用"></a>19.12 IO+Properties的联合应用</h3><p>IO流：文件的读和写。</p>
<p>Properties:是一个Map集合，key和value都是String类型。</p>
<p><strong>以后经常改变的数据，可以单独写到一个文件中，使用程序动态读取</strong>。 将来只需要修改这个文件的内容，java代码不需要改动，不需要重新编译，服务器也不需要重启。就可以拿到动态的信息。<strong>类似于以上机制的这种文件被称为==配置文件==。</strong></p>
<p>当配置文件中的内容格式是：</p>
<p>key1=value1</p>
<p>key2=value2</p>
<p>…</p>
<p>时，我们把这种配置文件叫做**==属性配置文件==**。</p>
<p>java规范中有要求：<strong>属性配置文件建议以 <code>.properties</code> 结尾</strong>，但这不是必须的。</p>
<p><code>Properties</code>  类就是专门存放属性配置文件内容的一个类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java">FileInputStream fileInputStream = <span class="hljs-keyword">null</span>;<br><span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 新建一个输入流对象</span><br>    fileInputStream = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">&quot;src\\userinfo.properties&quot;</span>);<br>    <span class="hljs-comment">// 新建一个 Map 集合</span><br>    Properties properties = <span class="hljs-keyword">new</span> Properties();<br>    <span class="hljs-comment">// 调用 Properties 对象的 load 方法将文件中的数据加载到 Map 集合中。</span><br>    <span class="hljs-comment">// 文件中的数据顺着管道加载到Map集合中，其中等号左边做 key，右边做 value</span><br>    properties.load(fileInputStream);<br><br>    <span class="hljs-comment">// 通过 key 获取 value</span><br>    System.out.println(properties.getProperty(<span class="hljs-string">&quot;username&quot;</span>));<br>    System.out.println(properties.getProperty(<span class="hljs-string">&quot;password&quot;</span>));<br>&#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>    e.printStackTrace();<br>&#125; <span class="hljs-keyword">finally</span> &#123;<br>    <span class="hljs-keyword">if</span> (fileInputStream != <span class="hljs-keyword">null</span>) &#123;<br>        <span class="hljs-keyword">try</span> &#123;<br>            fileInputStream.close();<br>        &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>            e.printStackTrace();<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>


            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/Java-%E5%9F%BA%E7%A1%80/">Java 基础</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Java-%E5%9F%BA%E7%A1%80/">Java 基础</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/09/13/Java%E5%9F%BA%E7%A1%80-2021-09-13-%E5%A4%9A%E7%BA%BF%E7%A8%8B/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">20、多线程</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/09/13/Java%E5%9F%BA%E7%A1%80-2021-09-13-%E9%9B%86%E5%90%88/">
                        <span class="hidden-mobile">18、集合</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  <script  src="https://cdn.jsdelivr.net/npm/tocbot@4.12.3/dist/tocbot.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4.3.1/anchor.min.js" ></script>



  <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js" ></script>



  <script  src="/js/local-search.js" ></script>






  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2.0.12/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>














  
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiaoxuehua.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/caidai.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/love.js"></script>
<script src="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<script src="//cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js"></script>



<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>

  <!--动态线条背景-->
  <script type="text/javascript" color="70,119,184" opacity='1' zIndex="-2" count="200" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"model":{"jsonPath":"/live2dw/assets/koharu.model.json"},"display":{"position":"left","width":200,"height":400},"mobile":{"show":false},"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
